﻿using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Abp.Authorization;
using MimeKit;
using pandx.Mulan.Authorization;
using pandx.Mulan.Dto;
using pandx.Mulan.Folders;
using pandx.Mulan.Helpers;
using pandx.Mulan.Logging.Dto;
using pandx.Mulan.Net.MimeTypes;
using pandx.Mulan.Storage;

namespace pandx.Mulan.Logging
{
    public class WebLogAppService : MulanAppServiceBase, IWebLogAppService
    {
        private readonly IAppFolder _appFolder;
        private readonly ITempFileCacheManager _tempFileCacheManager;

        public WebLogAppService(IAppFolder appFolder, ITempFileCacheManager tempFileCacheManager)
        {
            _appFolder = appFolder;
            _tempFileCacheManager = tempFileCacheManager;
        }


        [AbpAuthorize(AppPermissions.Pages_Administration_Maintenances_Browse)]
        public GetLatestWebLogsOutput GetLatestWebLogs()
        {
            var directory = new DirectoryInfo(_appFolder.WebLogsFolder);
            if (!directory.Exists)
            {
                return new GetLatestWebLogsOutput { LatestWebLogLines = new List<string>() };
            }

            var latestLogFile = directory.GetFiles("*.txt", SearchOption.AllDirectories)
                .OrderByDescending(f => f.LastWriteTime)
                .FirstOrDefault();

            if (latestLogFile == null)
            {
                return new GetLatestWebLogsOutput();
            }

            var lines = AppFileHelper.ReadLines(latestLogFile.FullName).Reverse().Take(1000).ToList();

            var logLineCount = 0;
            var lineCount = 0;
            foreach (var line in lines)
            {
                if (line.StartsWith("DEBUG") || line.StartsWith("INFO") || line.StartsWith("WARN") ||
                    line.StartsWith("ERROR") || line.StartsWith("FATAL"))
                {
                    logLineCount++;
                }

                lineCount++;
                if (logLineCount == 100)
                {
                    break;
                }
            }

            return new GetLatestWebLogsOutput
            {
                LatestWebLogLines = lines.Take(lineCount).Reverse().ToList()
            };
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_Maintenances_Export)]
        public FileDto DownloadWebLogs()
        {
            var logFiles = GetAllLogFiles();
            var zipFileDto = new FileDto("pandx.mulan.logs.zip", MimeTypeNames.ApplicationZip);
            using var outputZipFileStream = new MemoryStream();
            using var zipStream = new ZipArchive(outputZipFileStream, ZipArchiveMode.Create);
            foreach (var logFile in logFiles)
            {
                var entry = zipStream.CreateEntry(logFile.Name);
                using var entryStream = entry.Open();
                using var fs = new FileStream(logFile.FullName, FileMode.Open, FileAccess.Read,
                    FileShare.ReadWrite, bufferSize: 0x1000, FileOptions.SequentialScan);
                fs.CopyTo(entryStream);
                entryStream.Flush();
            }

            _tempFileCacheManager.SetFile(zipFileDto.FileToken, outputZipFileStream.ToArray());

            return zipFileDto;
        }

        private List<FileInfo> GetAllLogFiles()
        {
            var directory = new DirectoryInfo(_appFolder.WebLogsFolder);
            return directory.GetFiles("*.*", SearchOption.TopDirectoryOnly).ToList();
        }
    }
}